package com.wondertek.common.util.base;

import cn.hutool.core.util.IdUtil;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.messaging.*;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author: gongjiangtao
 * @date: 2024/7/24 13:44
 * @Description: Google_FireBase推送工具类
 * @Version: 1.0
 */
@Slf4j
public class FireBaseUtil {
    //获取AndroidConfig.Builder对象
    private static final com.google.firebase.messaging.AndroidConfig.Builder androidConfigBuilder = AndroidConfig.builder();
    //获取AndroidNotification.Builder对象
    private static final AndroidNotification.Builder androidNotifiBuilder = AndroidNotification.builder();

    private static final String JSON_PATH = "fcm/iotweb-167a5-firebase-adminsdk-koo6d-5ef8f1b064.json";
    private static final String DATA_URL = "https://xxxx.firebaseio.com/";

    // FirebaseApp实例
    private static FirebaseApp firebaseAppInstance;


    /**
     * 初始化SDK
     *
     * @throws IOException
     */
    private static synchronized void initSDK() throws IOException {
        if (firebaseAppInstance == null) {
            InputStream serviceAccount = Thread.currentThread().getContextClassLoader().getResourceAsStream(JSON_PATH);
            FirebaseOptions options = new FirebaseOptions.Builder()
                    .setCredentials(GoogleCredentials.fromStream(serviceAccount))
                    .setDatabaseUrl(DATA_URL).build();
            // 初始化firebaseApp
            firebaseAppInstance = FirebaseApp.initializeApp(options);
        }
    }

    /**
     * 获取FirebaseApp实例
     *
     * @return FirebaseApp实例
     * @throws IOException
     */
    public static FirebaseApp getFirebaseApp() throws IOException {
        if (firebaseAppInstance == null) {
            initSDK();
        }
        return firebaseAppInstance;
    }

    /**
     * 获取Message.Builder对象
     *
     * @param title       标题
     * @param body        内容
     * @param collapseKey 避免发送重复的消息给设备，节省网络带宽和设备资源
     * @param map
     * @return
     */
    private static Message.Builder getBuilder(String title, String body, String collapseKey, Map<String, String> map) {
        return Message.builder()
                .setNotification(Notification.builder().setTitle(title).setBody(body).build())
                .setAndroidConfig(AndroidConfig.builder()
                        .setTtl(3600 * 1000)
                        .setCollapseKey(collapseKey)
                        .setPriority(AndroidConfig.Priority.HIGH)
                        .setNotification(AndroidNotification.builder()
                                .setTitle(title)
                                .setBody(body)
                                .build())
                        .build())
                .setApnsConfig(ApnsConfig.builder()
                        .putHeader("apns-priority", "10")
                        .putHeader("apns-collapse-id", collapseKey)
                        .setAps(Aps.builder()
                                .setBadge(42)
                                .build())
                        .build()).putAllData(map);
    }

    /**
     * 单设备推送
     *
     * @param token   注册token
     * @param title   推送题目
     * @param body    推送内容
     * @param isAsync 是否异步
     * @return
     * @throws IOException
     * @throws FirebaseMessagingException
     */
    public static void pushSingle(String token, String title, String body, boolean isAsync, Map<String, String> map) throws IOException, FirebaseMessagingException {
        //获取实例
        FirebaseApp firebaseApp = getFirebaseApp();
        //构建消息内容
        String collapseKey = IdUtil.fastSimpleUUID();
        Message message = getBuilder(title, body, collapseKey, map)
                .setToken(token)
                .build();
        //发送后，返回messageID
        if (isAsync) {
            FirebaseMessaging.getInstance(firebaseApp).sendAsync(message);
        } else {
            String response = FirebaseMessaging.getInstance(firebaseApp).send(message);
            log.info("单设备推送成功 :{}", response);
        }
    }

    /**
     * 多设备推送
     *
     * @param token   注册token
     * @param title   推送题目
     * @param body    推送内容
     * @param isAsync 是否异步
     * @return
     * @throws IOException
     * @throws FirebaseMessagingException
     */
    public static void pushBatch(List<String> token, String title, String body, boolean isAsync, Map<String, String> map) throws IOException, FirebaseMessagingException {
        //获取实例
        FirebaseApp firebaseApp = getFirebaseApp();
        //构建消息内容
        String collapseKey = IdUtil.fastSimpleUUID();
        MulticastMessage message = getMulticastBuilder(title, body, collapseKey, map)
                .addAllTokens(token)
                .build();
        //发送后，返回messageID
        if (isAsync) {
            FirebaseMessaging.getInstance(firebaseApp).sendEachForMulticastAsync(message);
        } else {
            BatchResponse response = FirebaseMessaging.getInstance(firebaseApp).sendEachForMulticast(message);
            log.info("多设备推送成功 :{}", response);
        }
    }


    /**
     * 获取Message.Builder对象
     *
     * @param title       标题
     * @param body        内容
     * @param collapseKey 避免发送重复的消息给设备，节省网络带宽和设备资源
     * @param map
     * @return
     */
    private static MulticastMessage.Builder getMulticastBuilder(String title, String body, String collapseKey, Map<String, String> map) {
        return MulticastMessage.builder()
                .setNotification(Notification.builder().setTitle(title).setBody(body).build())
                .setAndroidConfig(AndroidConfig.builder()
                        .setTtl(3600 * 1000)
                        .setCollapseKey(collapseKey)
                        .setPriority(AndroidConfig.Priority.HIGH)
                        .setNotification(AndroidNotification.builder()
                                .setTitle(title)
                                .setBody(body)
                                .build())
                        .build())
                .setApnsConfig(ApnsConfig.builder()
                        .putHeader("apns-priority", "10")
                        .putHeader("apns-collapse-id", collapseKey)
                        .setAps(Aps.builder()
                                .setBadge(42)
                                .build())
                        .build()).putAllData(map);
    }

    /**
     * 给设备订阅主题
     *
     * @param tokens  设备的token,最大1000个
     * @param topic   要添加的主题
     * @param isAsync 是否异步
     * @return
     * @throws FirebaseMessagingException
     * @throws IOException
     */
    public static void subscribeToTopic(List<String> tokens, String topic, boolean isAsync) throws FirebaseMessagingException, IOException {
        //获取实例
        FirebaseApp firebaseApp = getFirebaseApp();
        List<List<String>> lists = splitList(tokens, 1000);
        for (List<String> list : lists) {
            //订阅，返回主题管理结果对象。
            if (isAsync) {
                FirebaseMessaging.getInstance(firebaseApp).subscribeToTopicAsync(list, topic);
            } else {
                TopicManagementResponse response = FirebaseMessaging.getInstance(firebaseApp).subscribeToTopic(list, topic);
                log.info("添加设备主题，成功：{}，失败：{}", response.getSuccessCount(), response.getFailureCount());
            }
        }
    }

    /**
     * 给设备取消订阅主题
     *
     * @param tokens  设备的token,最大1000个
     * @param topic   要添加的主题
     * @param isAsync 是否异步
     * @throws FirebaseMessagingException
     * @throws IOException
     */
    public static void unSubscribeFromTopic(List<String> tokens, String topic, boolean isAsync) throws FirebaseMessagingException, IOException {
        //获取实例
        FirebaseApp firebaseApp = getFirebaseApp();
        List<List<String>> lists = splitList(tokens, 1000);
        for (List<String> list : lists) {
            if (isAsync) {
                FirebaseMessaging.getInstance(firebaseApp).unsubscribeFromTopicAsync(list, topic);
            } else {
                TopicManagementResponse response = FirebaseMessaging.getInstance(firebaseApp).unsubscribeFromTopic(list, topic);
                log.info("添加设备主题，成功：{}，失败：{}", response.getSuccessCount(), response.getFailureCount());
            }
        }
    }

    /**
     * 按主题推送
     *
     * @param topic   主题的名字
     * @param title   消息题目
     * @param body    消息体
     * @param isAsync 是否异步
     * @return
     * @throws FirebaseMessagingException
     * @throws IOException
     */
    public static void sendTopicMes(String topic, String title, String body, boolean isAsync, Map<String, String> map) throws FirebaseMessagingException, IOException {
        //获取实例
        FirebaseApp firebaseApp = getFirebaseApp();
        //构建消息
        String collapseKey = IdUtil.fastSimpleUUID();
        Message message = getBuilder(title, body, collapseKey, map)
                .setTopic(topic)
                .build();
        //发送后，返回messageID
        if (isAsync) {
            FirebaseMessaging.getInstance(firebaseApp).sendAsync(message);
        } else {
            String response = FirebaseMessaging.getInstance(firebaseApp).send(message);
            log.info("主题推送成功:{}", response);
        }
    }


    /**
     * 将list分割成指定大小的分组
     *
     * @param list
     * @param groupSize
     * @return
     */
    private static List<List<String>> splitList(List<String> list, int groupSize) {
        int length = list.size();
        return IntStream.range(0, (length + groupSize - 1) / groupSize)
                .mapToObj(i -> list.subList(i * groupSize, Math.min((i + 1) * groupSize, length)))
                .collect(Collectors.toList());
    }
}
